<?php

class FormAction extends FormBase
{

  public $sortField;

  public $sortDirection = 'ASC';

  public $moduleActions;

  /**
   * @var Form
   */
  protected $form;

  protected $action;

  protected $template;

  protected $layout;

  protected $data = array();

  protected $errors;

  protected $view;

  public function __construct(Form $form)
  {
    global $response;

    $this->form = $form;

    $this->moduleActions = array(
      'view_all' => array('route' => Simplify::request()->route()),
      'create' => array('route' => Simplify::request()->route(), 'params' => array('action' => 'create'))
    );
  }

  public function getName()
  {
    return strtolower(substr(get_class($this), strlen('FormAction_')));
  }

  public function getErrors()
  {
    return $this->errors;
  }

  public function execute()
  {
    //
  }

  public function render()
  {
    $data = $this->getIterator();

    $elements = $this->form->getElements($this->action);

    if (Simplify::request()->json()) {
      $data = $data->getAll();

      $_elements = array();
      while ($element = $elements->next()) {
        $_elements = array('name' => $element->getName(), 'title' => $element->getTitle());
      }
      $elements = $_elements;
    }

    $view = $this->getView();

    $view->set('pk', $this->form->getPk());
    $view->set('form', $this->form);
    $view->set('action', $this->action);
    $view->set('route', $this->form->route);
    $view->set('data', $data);
    $view->set('elements', $elements);
    $view->set('action_title', $this->getTitle());
    $view->set('module_title', $this->form->getTitle());

    $view->set('filters', $this->form->getFilters());

    $view->setTemplate($this->getTemplate());

    return $view;
  }

  public function gateway()
  {
    return $this->form->gateway();
  }

  public function getData()
  {
    return $this->data;
  }

  public function setData($data)
  {
    $this->data = & $data;
    return $this;
  }

  public function setDataFromPost()
  {
    $post = Simplify::request()->post();

    $elements = $this->form->getElements($this->action);

    $data = $this->getIterator();

    while ($row = $data->next()) {
      while ($element = $elements->next()) {
        if ($element->getField() == $this->form->getPk()) {
          continue;
        }

        try {
          $element->setDataFromPost($row, $post, $this->action);
        }
        catch (ValidationException $e) {
          $this->errors = array_merge((array) $this->errors, (array) $e->getErrors());
        }
      }

      foreach ($this->form->getFilters() as $filter) {
        $filter->setDataFromPost($row);
      }
    }

    if (! empty($this->errors)) {
      throw new ValidationException($this->errors);
    }
  }

  protected function hasPostData()
  {
    return Simplify::request()->method('POST');
  }

  /**
   *
   * @param string $action
   * @param string $type
   * @return View
   */
  public function getView($type = null)
  {
    if (empty($this->view)) {
      if (is_null($type)) {
        switch (true) {
          case Simplify::request()->json() :
            $type = 'JSON';
            break;

          case Simplify::request()->xml() :
            $type = 'XML';
            break;

          default :
            $type = 'PHP';
        }
      }

      $this->view = View::factory($type);
    }

    return $this->view;
  }

  public function setTemplate($template)
  {
    $this->template = $template;
  }

  protected function getTemplate()
  {
    global $config;

    if (empty($this->template)) {
      $this->template = $config['views_dir'] . '/form/form_' . $this->getName() . '_view.php';
    }
    elseif (! sy_path_is_absolute($this->template)) {
      $this->template = $config['views_dir'] . '/form/form_' . $this->template . '_view.php';
    }

    return $this->template;
  }

  public function setLayout($layout)
  {
    $this->layout = $layout;
  }

  protected function getLayout()
  {
    global $config;

    if (empty($this->layout)) {
      $this->layout = $config['views_dir'] . '/form/form_layout.php';
    }

    return $this->layout;
  }

  public function getIterator()
  {
    $iterator = $this->form->iteratorClass;
    return new $iterator($this->data, $this->form->viewClass);
  }

  public function executeCallback($callback)
  {
    $elements = $this->form->getElements();

    $errors = array();

    $data = $this->getIterator();

    $args = func_get_args();

    unset($args[0]);

    while ($element = $elements->next()) {
      try {
        $func = array($element, $callback);

        if (method_exists($func[0], $func[1])) {
          call_user_func_array($func, $args);
        }
      }
      catch (ValidationException $e) {
        $errors = array_merge($errors, ( array ) $e->getErrors());
      }
    }

    array_unshift($args, null);

    while ($row = $data->next()) {
      while ($element = $elements->next()) {
        $args[0] = &$row;

        try {
          $func = array($element, $callback);

          if (method_exists($func[0], $func[1])) {
            call_user_func_array($func, $args);
          }
        }
        catch (ValidationException $e) {
          $errors = array_merge($errors, ( array ) $e->getErrors());
        }
      }
    }

    if (! empty($errors)) {
      throw new ValidationException($errors);
    }
  }

}
